/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_httpd.htm
 *
 * Zhiqim Httpd is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.httpd.context;

import java.io.IOException;
import java.util.Map.Entry;

import org.zhiqim.httpd.HttpContext;
import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.context.core.Context;
import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.model.maps.HashMapSO;
import org.zhiqim.kernel.model.maps.HashMapSS;
import org.zhiqim.kernel.model.maps.MapSO;
import org.zhiqim.kernel.logging.Log;
import org.zhiqim.kernel.logging.LogFactory;
import org.zhiqim.kernel.util.Htmls;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.zml.Zml;
import org.zhiqim.zml.ZmlEngine;
import org.zhiqim.zml.Zmls;

/**
 * 对HttpRequest进行一级封装，实现相关的数据提取工具类，分隔HttpRequest代码
 * 
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 */
@AnAlias("ZmlContexts")
public class ZmlContexts implements ZmlContextConstants
{
    private static final Log log = LogFactory.getLog(ZmlContexts.class);
    
    /******************************************************************/
    //以下为获取ZML引擎和ZML的方法
    /******************************************************************/
    
    /**
     * 获取当前请求对应的ZML引擎
     * 
     * @param context       上下文环境
     * @return ZmlEngine    返回ZML引擎
     */
    public static ZmlEngine getZmlEngine(HttpContext context)
    {
        return ((Context)context).getZmlEngine();
    }
    
    /**
     * 获取当前请求对应的ZML引擎
     * 
     * @param request       请求
     * @return ZmlEngine    返回ZML引擎
     */
    public static ZmlEngine getZmlEngine(HttpRequest request)
    {
        return getZmlEngine(request.getContext());
    }
    
    /**
     * 获取当前请求对应的ZML引擎中的ZML
     * 
     * @param context       上下文环境
     * @param zmlPath       ZML路径
     * @return Zml          返回ZML对象
     */
    public static Zml getZml(HttpContext context, String zmlPath) throws IOException
    {
        ZmlEngine engine = getZmlEngine(context);
        if (engine == null)
            return null;
        
        return engine.getZml(zmlPath);
    }
    
    /**
     * 获取当前请求对应的ZML引擎中的ZML
     * 
     * @param request       请求
     * @param zmlPath       ZML路径
     * @return Zml          返回ZML对象
     */
    public static Zml getZml(HttpRequest request, String zmlPath) throws IOException
    {
        ZmlEngine engine = getZmlEngine(request);
        if (engine == null)
            return null;
        
        return engine.getZml(zmlPath);
    }
    
    /******************************************************************/
    //在Request下解释ZML内容
    /******************************************************************/
    
    /**
     * 解析ZML和[KEY/VALUE]得到内容
     * 
     * @param request       请求
     * @param zmlPath       ZML路径
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZmlPath(HttpRequest request, String zmlPath) throws Exception
    {
        ZmlEngine engine = getZmlEngine(request);
        if (engine == null)
            return null;
        
        Zml zml = engine.getZml(zmlPath);
        return parseZml(request, zml);
    }
    
    /**
     * 解析ZML和[KEY/VALUE]得到内容
     * 
     * @param request       请求
     * @param zmlPath       ZML路径
     * @param key           属性键
     * @param value         属性值
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZmlPath(HttpRequest request, String zmlPath, String key, Object value) throws Exception
    {
        return parseZmlPath(request, zmlPath, new HashMapSO(key, value));
    }
    
    /**
     * 解析ZML和属性表得到内容
     * 
     * @param request       请求
     * @param zmlPath       ZML路径
     * @param variableMap   变量表
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZmlPath(HttpRequest request, String zmlPath, MapSO variableMap) throws Exception
    {
        ZmlEngine engine = getZmlEngine(request);
        if (engine == null)
            return null;
        
        Zml zml = engine.getZml(zmlPath);
        return parseZml(request, zml, variableMap);
    }
    
    /**
     * 解析ZML内容和单一属性得到解析之后的内容
     * 
     * @param request       请求
     * @param content       指定ZML的内容
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZmlContent(HttpRequest request, String content) throws Exception
    {
        if (Validates.isEmptyBlank(content))
            return content;
        
        ZmlEngine engine = getZmlEngine(request);
        Zml zml = new Zml(engine, content);
        
        return parseZml(request, zml);
    }

    
    /**
     * 解析ZML内容和单一属性得到解析之后的内容
     * 
     * @param request       请求
     * @param content       指定ZML的内容
     * @param key           变量KEY
     * @param value         变量VALUE
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZmlContent(HttpRequest request, String content, String key, Object value) throws Exception
    {
        if (Validates.isEmptyBlank(content))
            return content;
        
        ZmlEngine engine = getZmlEngine(request);
        Zml zml = new Zml(engine, content);
        
        return parseZml(request, zml, new HashMapSO(key, value));
    }
    
    /**
     * 解析ZML内容和属性表得到解析之后的内容
     * 
     * @param request       请求
     * @param content       指定ZML的内容
     * @param variableMap   变量表
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZmlContent(HttpRequest request, String content, MapSO variableMap) throws Exception
    {
        if (Validates.isEmptyBlank(content))
            return content;
        
        ZmlEngine engine = getZmlEngine(request);
        Zml zml = new Zml(engine, content);
        
        return parseZml(request, zml, variableMap);
    }

    
    /**
     * 解析ZML和属性表得到解析之后的内容，提供请求和响应作为变量条件
     * 
     * @param request       请求
     * @param zml           ZML对象
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZml(HttpRequest request, Zml zml) throws Exception
    {
        return parseZml(request, zml, null);
    }
    
    /**
     * 解析ZML和属性表得到解析之后的内容，提供请求和响应作为变量条件
     * 
     * @param request       请求
     * @param zml           ZML对象
     * @param key           变量KEY
     * @param value         变量VALUE
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZml(HttpRequest request, Zml zml, String key, Object value) throws Exception
    {
        return parseZml(request, zml, new HashMapSO(key, value));
    }
    
    /**
     * 解析ZML和属性表得到解析之后的内容，提供请求和响应作为变量条件
     * 
     * @param request       请求
     * @param zml           ZML对象
     * @param variableMap   变量表
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZml(HttpRequest request, Zml zml, MapSO variableMap) throws Exception
    {
        //页面环境变量表，包括请求中参数和属性
        HashMapSO pageVariableMap = new HashMapSO();
        //1.先放参数，注意来自参数的数据由外部决定，这里要对其安全过滤
        HashMapSS paramMap = request.getParameterMap();
        if (!paramMap.isEmpty())
        {
            for (Entry<String, String> entry : paramMap.entrySet())
            {
                String key = entry.getKey();
                String value = Htmls.filterAll(entry.getValue());
                pageVariableMap.put(key, value);
            }
        }

        //2.再放属性，这里的数据来自Action本身，明确，不作过滤，和参数名相同时覆盖
        pageVariableMap.putAll(request.getAttributeMap());
        
        //3.自定义变量
        if (variableMap != null)
            pageVariableMap.putAll(variableMap);
        
        //请求环境变量表，包括请求、响应、会话和上下文环境等固定值
        //1.放置Session对应的三个数据
        if (request.getSession() != null)
        {
            pageVariableMap.put("sessionId", request.getSessionId());
            pageVariableMap.put("sessionUser", request.getSessionUser());
            pageVariableMap.put("sessionName", request.getSessionName());
        }
        
        //2.放置范围域
        pageVariableMap.put("request", request);
        pageVariableMap.put("response", request.getResponse());
        pageVariableMap.put("session", request.getSession());
        pageVariableMap.put("context", request.getContext());
        pageVariableMap.put("log", log);
        
        //2.上下文环境变量表两个，1)/conf/httpd.xml配置的，2)/resource/conf/context.zml，3)/resource/conf/context.xml配置的
        Context context = (Context)request.getContext();
        ZmlConfig config = context.getConfig();
        
        return Zmls.parse(zml, pageVariableMap, config);
    }
    
    /******************************************************************************************************************************/
    //在Context下解析ZML内容
    /******************************************************************************************************************************/

    /**
     * 解析ZML内容和单一属性得到解析之后的内容
     * 
     * @param context       上下文环境
     * @param content       指定ZML的内容
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZmlContent(HttpContext context, String content) throws Exception
    {
        if (Validates.isEmpty(content))
            return content;
            
        ZmlEngine engine = getZmlEngine(context);
        Zml zml = new Zml(engine, content);
        
        return parseZml(context, zml, null);
    }
    
    /**
     * 解析ZML内容和单一属性得到解析之后的内容
     * 
     * @param context       上下文环境
     * @param content       指定ZML的内容
     * @param key           变量KEY
     * @param value         变量VALUE
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZmlContent(HttpContext context, String content, String key, Object value) throws Exception
    {
        if (Validates.isEmpty(content))
            return content;
        
        ZmlEngine engine = getZmlEngine(context);
        Zml zml = new Zml(engine, content);
        
        return parseZml(context, zml, new HashMapSO(key, value));
    }
    
    /**
     * 解析ZML内容和属性表得到解析之后的内容
     * 
     * @param context       上下文环境
     * @param content       指定ZML的内容
     * @param variableMap   变量表
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZmlContent(HttpContext context, String content, MapSO variableMap) throws Exception
    {
        if (Validates.isEmpty(content))
            return content;
        
        ZmlEngine engine = getZmlEngine(context);
        Zml zml = new Zml(engine, content);
        
        return parseZml(context, zml, variableMap);
    }
    
    /**
     * 解析ZML和属性表得到解析之后的内容，提供请求和响应作为变量条件
     * 
     * @param context       上下文环境
     * @param zml           ZML对象
     * @param variableMap   变量表
     * @return String       解析之后的内容
     * @throws Exception    可能解析的异常 
     */
    public static String parseZml(HttpContext context, Zml zml, MapSO variableMap) throws Exception
    {
        //页面环境变量表，包括请求中参数和属性
        HashMapSO pageVariableMap = new HashMapSO();
        if (variableMap != null)
            pageVariableMap.putAll(variableMap);
        
        ZmlConfig config = ((Context)context).getConfig();
        return Zmls.parse(zml, pageVariableMap, config);
    }
}